package impl;

import java.util.ArrayList;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;

import api.IPostman;
import api.ISocializer;
import api.InvalidAuthenticationException;

import javax.ejb.EJB;
import javax.ejb.Schedule;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;

import entities.Friend;
import entities.Messageboard;
import entities.Usermessage;
import entities.Userphoto;
import entities.Userprofile;

/**
 * Session Bean implementation class Socializer
 */
@Stateless(name = "ISocializer")
@TransactionAttribute(value = TransactionAttributeType.REQUIRES_NEW)
public class Socializer implements ISocializer {
	@PersistenceContext(unitName = "PhaseBookPU")
	EntityManager em;

	@EJB(beanName = "IPostman")
	IPostman postman;

	static final long MILLIS_IN_A_DAY = 1000 * 60 * 60 * 24;

	/**
	 * Default constructor.
	 */
	public Socializer() {
		// TODO Auto-generated constructor stub
	}

	@Override
	public List<String> searchFriends(String searchString) {
		System.out.println("*** SOCIALIZER ***");
		System.out.println("*** Search User request ***");

		// Query query=em.createNamedQuery("searchUsers");
		// query.setParameter("email", searchString);
		// query.setParameter("name", searchString);
		Query query = em
				.createNativeQuery("SELECT Email FROM userprofiles WHERE name REGEXP '"
						+ searchString + "'");

		return query.getResultList();

	}

	@Override
	public boolean sendFriendshipInvitation(int fromId, int toId) {
		System.out.println("*** SOCIALIZER ***");
		System.out.println("*** Send Friendship request ***");

		Friend friend = new Friend();
		Userprofile userprofile1 = em.find(Userprofile.class, fromId);
		Userprofile userprofile2 = em.find(Userprofile.class, toId);

		friend.setUserprofile1(userprofile1);
		friend.setUserprofile2(userprofile2);

		em.persist(friend);

		String message = "Hi " + userprofile2.getEmail() + "\n\n"
				+ "You have a frindship request from '"
				+ userprofile1.getEmail() + "'\n\n";

		postman.sendMail(userprofile2.getEmail(), "Friendship Request", message);

		return true;

	}

	@Override
	public List<Friend> getPendingFriendshipRequests(int uid) {
		System.out.println("*** AUTHENTICATOR ***");
		System.out.println("*** Pending Friendship requests ***");

		Query query = em.createNamedQuery("getPendingRequests");
		query.setParameter("userId", uid);

		return query.getResultList();

	}

	@Override
	public boolean confirmFriendshipRequest(int uid, int requesterdId) {
		System.out.println("*** SOCIALIZER ***");
		System.out.println("*** Confirm Friendship request ***");

		Query query = em.createNamedQuery("getRequest");
		query.setParameter("userId1", requesterdId);
		query.setParameter("userId2", uid);

		Friend friend = (Friend) query.getSingleResult();

		friend.setRelationshipActive(true);

		em.persist(friend);

		Userprofile userprofile1 = em.find(Userprofile.class, requesterdId);
		Userprofile userprofile2 = em.find(Userprofile.class, uid);

		String message = "Hi " + userprofile1.getEmail() + "\n\n"
				+ "Your friendship request to '" + userprofile2.getEmail()
				+ "' has been accepted\n\n";

		postman.sendMail(userprofile1.getEmail(), "Friendship Accepted",
				message);

		return true;

	}

	@Override
	public boolean isFriendWith(int baseId, int friendId) {
		System.out.println("*** SOCIALIZER ***");
		System.out.println("*** Check Friends ***");

		Query query = em.createNamedQuery("isFriend");
		query.setParameter("userId1", baseId);
		query.setParameter("userId2", friendId);

		Integer id = (Integer) query.getSingleResult();

		if (id != null)
			return true;

		return false;

	}

	@Override
	public List<Userprofile> getMyFriends(int uid) {
		System.out.println("*** SOCIALIZER ***");
		System.out.println("*** Get My Friends ***");
		List<Userprofile> friendsList = new ArrayList<Userprofile>();

		Query query = em.createNamedQuery("myFriends");
		query.setParameter("userId", uid);

		List<Friend> friendships = (List<Friend>) query.getResultList();

		for (Friend friend : friendships) {
			if (friend.getUserprofile1().getUserId() == uid)
				friendsList.add(friend.getUserprofile2());
			else
				friendsList.add(friend.getUserprofile1());
		}

		return friendsList;
	}

	@Override
	public boolean publishPublicMessage(int ownerId, int posterId,
			String message, int photoId) throws InvalidAuthenticationException {
		System.out.println("*** SOCIALIZER ***");
		System.out.println("*** Publish public message***");

		Messageboard msgBoard = getMessageBoard(ownerId,
				MessageBoardsType.PUBLIC);
		if (msgBoard == null)
			return false;

		Userprofile posterUser = em.find(Userprofile.class, posterId);

		return publishUserMessage(msgBoard, posterUser, message, photoId);

	}

	@Override
	public boolean publishPrivateMessage(int ownerId, int posterId,
			String message, int photoId) {
		System.out.println("*** SOCIALIZER ***");
		System.out.println("*** Publish private message***");

		if ((ownerId != posterId) && (!isFriendWith(ownerId, posterId))) {
			System.out
					.println("*** Publishing private message to no friend ***");
			return false;
		}

		Messageboard msgBoard = getMessageBoard(ownerId,
				MessageBoardsType.PRIVATE);
		if (msgBoard == null)
			return false;

		Userprofile posterUser = em.find(Userprofile.class, posterId);

		return publishUserMessage(msgBoard, posterUser, message, photoId);

	}

	@Override
	public List<Usermessage> getPublicMessageList(int uid) {
		System.out.println("*** SOCIALIZER ***");
		System.out.println("*** Get public user board messages***");

		return getUserBoardMessage(uid, MessageBoardsType.PUBLIC);
	}

	@Override
	public List<Usermessage> getPrivateMessageList(int uid) {
		System.out.println("*** SOCIALIZER ***");
		System.out.println("*** Get private user board messages***");

		return getUserBoardMessage(uid, MessageBoardsType.PRIVATE);
	}

	@Override
	public int addPhoto(int uid, String photoPath) {
		System.out.println("*** SOCIALIZER ***");
		System.out.println("*** Add User Photo ***");
		Userphoto photo = new Userphoto();
		photo.setPhotoPath(photoPath);

		em.persist(photo);

		return photo.getId();

	}

	@Schedule(minute = "*/1", hour = "*", persistent = false)
	public void digestDayilyUserMessages() {

		System.out.println("*** SOCIALIZER ***");
		System.out.println("*** Daily Digest ***");

		Query query = em.createNamedQuery("getDailyMessages");

		Date yesterday = new Date(new java.util.Date().getTime()
				- MILLIS_IN_A_DAY);
		query.setParameter("yesterday", yesterday);

		List<Usermessage> messages = query.getResultList();

		System.out.println("*** Daily Digest: " + messages.size()
				+ " messages to send");

		HashMap<String, List<Usermessage>> hash = new HashMap<String, List<Usermessage>>();

		for (Usermessage m : messages) {

			if (!m.getUserboard().getUserprofile().getNotify_Digest())
				continue;

			String email = m.getUserboard().getUserprofile().getEmail();
			List<Usermessage> mappedML = hash.get(email);
			if (mappedML == null) {
				ArrayList<Usermessage> mu = new ArrayList<Usermessage>();
				mu.add(m);
				hash.put(email, mu);
			} else {
				mappedML.add(m);
			}
		}

		for (Entry<String, List<Usermessage>> entry : hash.entrySet()) {
			String email = entry.getKey();
			messages = entry.getValue();
			StringBuffer buf = new StringBuffer();

			buf.append("Hello again from PhaseBook");
			buf.append("\n\n");
			buf.append("Here is what happened today: ");
			buf.append("\n");

			for (Usermessage message : messages) {

				buf.append("-------------------------\n");
				buf.append("From: ");
				buf.append(message.getUserprofile1().getName());
				buf.append("\n");

				buf.append(message.getTextMessage());
				buf.append("\n");
				buf.append("Posted On: ");
				buf.append(message.getPostedOn().toString());

				buf.append("\n-------------------------\n\n\n");

			}

			postman.sendMail(email, "PhaseBook Daily Digest", buf.toString());
			System.out.println("*** BUF");
			System.out.println(buf.toString());

		}

		// Usermessage msg = em.find(Usermessage.class, 1);
		// int thisDay = Calendar.getInstance().get(Calendar.DAY_OF_MONTH);
		// int thisMonth = Calendar.getInstance().get(Calendar.MONTH);
		// int thisYear = Calendar.getInstance().get(Calendar.YEAR);
		//
		// System.out.println("MEssage have the following date:"+msg.getPostedOn().getDay());
	}

	private Messageboard getMessageBoard(int uid, MessageBoardsType type) {

		Query query = em.createNamedQuery("getUserMessageBoard");
		query.setParameter("userId", uid);
		query.setParameter(1, type.ordinal());

		return (Messageboard) query.getSingleResult();

	}

	private boolean publishUserMessage(Messageboard msgBoard,
			Userprofile posterUser, String message, int photoId) {

		// Create a user message board
		Usermessage userMessage = new Usermessage();
		userMessage.setUserprofile1(posterUser);
		userMessage.setUserboard(msgBoard);

		if (message != null)
			userMessage.setTextMessage(message);

		if (photoId != 0) {
			Userphoto userPhoto = em.find(Userphoto.class, photoId);
			userMessage.setPhotoId(userPhoto);
		}

		userMessage.setPostedOn(new Date());

		em.persist(userMessage);

		if (msgBoard.getUserprofile().getNotify_OnChange()) {

			String emailMessage = "Hi " + msgBoard.getUserprofile().getEmail()
					+ "\n\n" + "You have a new message from '"
					+ posterUser.getEmail() + "'";

			postman.sendMail(msgBoard.getUserprofile().getEmail(),
					"New board message", emailMessage);
		}

		return true;

	}

	private List<Usermessage> getUserBoardMessage(int uid,
			MessageBoardsType type) {

		Query query = em.createNamedQuery("getUserBoardMessages");
		query.setParameter("userId", uid);
		query.setParameter(1, type.ordinal());

		return query.getResultList();

	}
}
